<template>
  <view class="tetris-container">
    <!-- 游戏标题与状态信息 -->
    <view class="game-header">
      <h1>俄罗斯方块</h1>
      <view class="game-stats">
        <view class="stat-item">
          <span class="stat-label">分数</span>
          <span class="stat-value">{{ score }}</span>
        </view>
        <view class="stat-item">
          <span class="stat-label">行数</span>
          <span class="stat-value">{{ lines }}</span>
        </view>
        <view class="stat-item">
          <span class="stat-label">等级</span>
          <span class="stat-value">{{ level }}</span>
        </view>
      </view>
    </view>

    <!-- 游戏主区域（游戏区 + 预览区） -->
    <view class="game-main">
      <!-- 游戏网格区域 -->
      <view class="game-board" :style="{ width: boardWidth + 'px', height: boardHeight + 'px' }">
        <!-- 已落下的方块 -->
        <view v-for="(row, rowIdx) in board" :key="rowIdx" class="board-row" :style="{ height: cellSize + 'px' }">
          <view v-for="(cell, colIdx) in row" :key="colIdx" class="board-cell" :style="{ 
              width: cellSize + 'px', 
              height: cellSize + 'px',
              backgroundColor: cell ? getBlockColor(cell) : '#f0f0f0',
              border: '1px solid #e0e0e0'
            }"></view>
        </view>

        <!-- 当前活动方块 -->
        <view v-for="(block, idx) in activeBlock.shape" :key="idx" class="active-block" :style="{ 
            left: (activeBlock.x + block.x) * cellSize + 'px',
            top: (activeBlock.y + block.y) * cellSize + 'px',
            width: cellSize + 'px',
            height: cellSize + 'px',
            backgroundColor: getBlockColor(activeBlock.type),
            border: '1px solid #fff'
          }"></view>
      </view>

      <!-- 下一个方块预览区 -->
      <view class="next-block-preview">
        <h3>下一个</h3>
        <view class="preview-container" :style="{ width: previewWidth + 'px', height: previewHeight + 'px' }">
          <view v-for="(block, idx) in nextBlock.shape" :key="idx" class="preview-block" :style="{ 
              left: (previewOffsetX + block.x) * cellSize + 'px',
              top: (previewOffsetY + block.y) * cellSize + 'px',
              width: cellSize + 'px',
              height: cellSize + 'px',
              backgroundColor: getBlockColor(nextBlock.type),
              border: '1px solid #fff'
            }"></view>
        </view>
      </view>
    </view>

    <!-- 游戏控制按钮 -->
    <view class="game-controls">
      <button @click="startGame" v-if="!isPlaying && !isGameOver">开始游戏</button>
      <button @click="pauseGame" v-if="isPlaying && !isPaused && !isGameOver">暂停</button>
      <button @click="resumeGame" v-if="isPaused && !isGameOver">继续</button>
      <button @click="restartGame" v-if="isGameOver || isPlaying">重新开始</button>
    </view>

    <!-- 移动端控制按钮 -->
    <view class="mobile-controls" v-if="isMobile">
      <view class="control-row">
        <button @click="rotateBlock" class="control-btn rotate">旋转</button>
      </view>
      <view class="control-row">
        <button @click="() => moveBlock(-1, 0)" class="control-btn left">左移</button>
        <button @click="() => moveBlock(0, 1)" class="control-btn down">下移</button>
        <button @click="() => moveBlock(1, 0)" class="control-btn right">右移</button>
      </view>
      <view class="control-row">
        <button @click="dropBlock" class="control-btn drop">直接落地</button>
      </view>
    </view>

    <!-- 游戏结束弹窗 -->
    <view class="game-over-modal" v-if="isGameOver">
      <view class="modal-content">
        <h2>游戏结束!</h2>
        <p class="final-score">最终得分: {{ score }}</p>
        <p class="final-lines">消除行数: {{ lines }}</p>
        <button @click="restartGame">再来一局</button>
      </view>
    </view>

    <!-- 操作说明 -->
    <view class="game-instructions">
      <p>桌面端: ←→移动 | ↑旋转 | ↓加速下落 | 空格直接落地</p>
      <p>移动端: 左右滑动移动 | 点击屏幕旋转 | 向下滑动加速</p>
    </view>
  </view>
</template>

<script setup>
  import {
    ref,
    onMounted,
    onUnmounted,
    computed,
    watch
  } from 'vue';

  // 判断是否为移动设备
  const isMobile = ref(false);

  // -------------------------- 游戏配置 --------------------------
  const cellSize = 30; // 每个格子大小（px）
  const boardCols = 10; // 游戏区列数
  const boardRows = 20; // 游戏区行数
  const previewCols = 4; // 预览区列数
  const previewRows = 4; // 预览区行数

  // 计算尺寸
  const boardWidth = boardCols * cellSize;
  const boardHeight = boardRows * cellSize;
  const previewWidth = previewCols * cellSize;
  const previewHeight = previewRows * cellSize;

  // 方块形状定义（I、O、T、L、J、S、Z 七种基础形状）
  const TETROMINOS = {
    I: {
      shape: [{
        x: 0,
        y: 0
      }, {
        x: 1,
        y: 0
      }, {
        x: 2,
        y: 0
      }, {
        x: 3,
        y: 0
      }],
      color: '#00ffff' // 青色
    },
    O: {
      shape: [{
        x: 0,
        y: 0
      }, {
        x: 1,
        y: 0
      }, {
        x: 0,
        y: 1
      }, {
        x: 1,
        y: 1
      }],
      color: '#ffff00' // 黄色
    },
    T: {
      shape: [{
        x: 1,
        y: 0
      }, {
        x: 0,
        y: 1
      }, {
        x: 1,
        y: 1
      }, {
        x: 2,
        y: 1
      }],
      color: '#a020f0' // 紫色
    },
    L: {
      shape: [{
        x: 2,
        y: 0
      }, {
        x: 0,
        y: 1
      }, {
        x: 1,
        y: 1
      }, {
        x: 2,
        y: 1
      }],
      color: '#ff8c00' // 橙色
    },
    J: {
      shape: [{
        x: 0,
        y: 0
      }, {
        x: 0,
        y: 1
      }, {
        x: 1,
        y: 1
      }, {
        x: 2,
        y: 1
      }],
      color: '#0000ff' // 蓝色
    },
    S: {
      shape: [{
        x: 1,
        y: 0
      }, {
        x: 2,
        y: 0
      }, {
        x: 0,
        y: 1
      }, {
        x: 1,
        y: 1
      }],
      color: '#00ff00' // 绿色
    },
    Z: {
      shape: [{
        x: 0,
        y: 0
      }, {
        x: 1,
        y: 0
      }, {
        x: 1,
        y: 1
      }, {
        x: 2,
        y: 1
      }],
      color: '#ff0000' // 红色
    }
  };

  // 方块类型列表（用于随机生成）
  const TETROMINO_TYPES = Object.keys(TETROMINOS);

  // -------------------------- 游戏状态 --------------------------
  // 游戏面板（二维数组，0 表示空，非 0 表示对应类型的方块）
  const board = ref([]);
  // 当前活动方块（位置 + 形状 + 类型）
  const activeBlock = ref({
    x: 0,
    y: 0,
    shape: [],
    type: ''
  });
  // 下一个方块
  const nextBlock = ref({
    shape: [],
    type: ''
  });
  // 游戏状态变量
  const score = ref(0);
  const lines = ref(0);
  const level = ref(1);
  const isPlaying = ref(false);
  const isPaused = ref(false);
  const isGameOver = ref(false);
  // 游戏速度（毫秒/帧）
  const gameSpeed = ref(1000);
  // 定时器引用
  const gameTimer = ref(null);
  // 触摸控制相关
  const touchStartX = ref(0);
  const touchStartY = ref(0);
  const touchStartTime = ref(0);

  // -------------------------- 计算属性 --------------------------
  // 预览区方块偏移量（让预览方块居中显示）
  const previewOffsetX = computed(() => {
    if (!nextBlock.value.shape.length) return 0;
    const minX = Math.min(...nextBlock.value.shape.map(b => b.x));
    const maxX = Math.max(...nextBlock.value.shape.map(b => b.x));
    return Math.floor((previewCols - (maxX - minX + 1)) / 2) - minX;
  });
  const previewOffsetY = computed(() => {
    if (!nextBlock.value.shape.length) return 0;
    const minY = Math.min(...nextBlock.value.shape.map(b => b.y));
    const maxY = Math.max(...nextBlock.value.shape.map(b => b.y));
    return Math.floor((previewRows - (maxY - minY + 1)) / 2) - minY;
  });

  // -------------------------- 工具函数 --------------------------
  // 初始化游戏面板
  const initBoard = () => {
    const newBoard = [];
    for (let y = 0; y < boardRows; y++) {
      newBoard[y] = Array(boardCols).fill(0);
    }
    board.value = newBoard;
  };

  // 随机生成一个方块
  const generateRandomBlock = () => {
    const type = TETROMINO_TYPES[Math.floor(Math.random() * TETROMINO_TYPES.length)];
    const shape = JSON.parse(JSON.stringify(TETROMINOS[type].shape)); // 深拷贝避免引用问题
    // 初始位置（水平居中，垂直顶部）
    const x = Math.floor((boardCols - Math.max(...shape.map(b => b.x)) - 1) / 2);
    const y = 0;
    return {
      x,
      y,
      shape,
      type
    };
  };

  // 获取方块颜色
  const getBlockColor = (type) => {
    return TETROMINOS[type]?.color || '#ccc';
  };

  // 检查方块位置是否合法（不越界、不碰撞）
  const isBlockValid = (blockX, blockY, blockShape) => {
    for (const b of blockShape) {
      const x = blockX + b.x;
      const y = blockY + b.y;
      // 检查边界
      if (x < 0 || x >= boardCols || y >= boardRows) return false;
      // 检查是否碰撞（忽略负的 y 值，允许方块从屏幕顶部外进入）
      if (y >= 0 && board.value[y][x] !== 0) return false;
    }
    return true;
  };

  // 将活动方块固定到面板上
  const lockBlockToBoard = () => {
    for (const b of activeBlock.value.shape) {
      const x = activeBlock.value.x + b.x;
      const y = activeBlock.value.y + b.y;
      if (y >= 0) { // 忽略屏幕顶部外的方块
        board.value[y][x] = activeBlock.value.type;
      }
    }
    // 检查是否游戏结束（方块超出顶部）
    if (activeBlock.value.y <= 0) {
      isGameOver.value = true;
      isPlaying.value = false;
      clearInterval(gameTimer.value);
      return;
    }
    // 生成下一个方块
    activeBlock.value = {
      ...nextBlock.value,
      x: Math.floor((boardCols - Math.max(...nextBlock.value.shape.map(b => b.x)) - 1) / 2),
      y: 0
    };
    nextBlock.value = generateRandomBlock();
    // 检查消除行
    checkLines();
  };

  // 检查并消除满行
  const checkLines = () => {
    let linesCleared = 0;
    const newBoard = [...board.value];

    for (let y = boardRows - 1; y >= 0; y--) {
      // 检查当前行是否满
      if (newBoard[y].every(cell => cell !== 0)) {
        linesCleared++;
        // 移除当前行，并在顶部添加空行
        newBoard.splice(y, 1);
        newBoard.unshift(Array(boardCols).fill(0));
        // 重新检查当前行（因为删除后下一行会移到当前位置）
        y++;
      }
    }

    if (linesCleared > 0) {
      board.value = newBoard;
      // 更新分数（根据行数和等级计算）
      const lineScores = [0, 40, 100, 300, 1200]; // 0、1、2、3、4行的基础分数
      score.value += lineScores[linesCleared] * level.value;
      lines.value += linesCleared;
      // 更新等级（每消除10行升一级，加速游戏）
      const newLevel = Math.floor(lines.value / 10) + 1;
      if (newLevel > level.value) {
        level.value = newLevel;
        gameSpeed.value = Math.max(100, 1000 - (level.value - 1) * 100); // 最低100ms
        if (isPlaying.value && !isPaused.value) {
          clearInterval(gameTimer.value);
          gameTimer.value = setInterval(moveBlockDown, gameSpeed.value);
        }
      }
    }
  };

  // -------------------------- 方块控制函数 --------------------------
  // 移动方块
  const moveBlock = (dx, dy) => {
    if (!isPlaying.value || isPaused.value || isGameOver.value) return;

    const newX = activeBlock.value.x + dx;
    const newY = activeBlock.value.y + dy;

    if (isBlockValid(newX, newY, activeBlock.value.shape)) {
      activeBlock.value.x = newX;
      activeBlock.value.y = newY;
      return true;
    } else if (dy > 0) { // 向下移动无效时，固定方块
      lockBlockToBoard();
      return false;
    }
    return false;
  };

  // 向下移动方块（自动下落）
  const moveBlockDown = () => {
    moveBlock(0, 1);
  };

  // 旋转方块（顺时针旋转）
  const rotateBlock = () => {
    if (!isPlaying.value || isPaused.value || isGameOver.value || activeBlock.value.type === 'O') return; // O型方块无需旋转

    const originalShape = activeBlock.value.shape;
    // 旋转算法：(x, y) → (y, -x)（顺时针旋转90度）
    const rotatedShape = originalShape.map(b => ({
      x: b.y,
      y: -b.x
    }));

    // 找到旋转后的最小x值，确保旋转后不会出现负坐标
    const minX = Math.min(...rotatedShape.map(b => b.x));
    const adjustedShape = rotatedShape.map(b => ({
      x: b.x - minX,
      y: b.y
    }));

    // 尝试直接旋转
    if (isBlockValid(activeBlock.value.x, activeBlock.value.y, adjustedShape)) {
      activeBlock.value.shape = adjustedShape;
      return;
    }

    // 尝试偏移旋转（左移、右移、上移，应对边界碰撞）
    const offsets = [-1, 1, -2, 2];
    for (const dx of offsets) {
      if (isBlockValid(activeBlock.value.x + dx, activeBlock.value.y, adjustedShape)) {
        activeBlock.value.x += dx;
        activeBlock.value.shape = adjustedShape;
        return;
      }
      for (const dy of offsets) {
        if (isBlockValid(activeBlock.value.x + dx, activeBlock.value.y + dy, adjustedShape)) {
          activeBlock.value.x += dx;
          activeBlock.value.y += dy;
          activeBlock.value.shape = adjustedShape;
          return;
        }
      }
    }
  };

  // 方块直接落地
  const dropBlock = () => {
    if (!isPlaying.value || isPaused.value || isGameOver.value) return;

    let newY = activeBlock.value.y;
    // 找到最大可下落的y值
    while (isBlockValid(activeBlock.value.x, newY + 1, activeBlock.value.shape)) {
      newY++;
    }

    if (newY > activeBlock.value.y) {
      activeBlock.value.y = newY;
      lockBlockToBoard();
    }
  };

  // -------------------------- 游戏控制函数 --------------------------
  // 开始游戏
  const startGame = () => {
    if (isPlaying.value) return;

    // 初始化游戏状态
    initBoard();
    score.value = 0;
    lines.value = 0;
    level.value = 1;
    gameSpeed.value = 1000;
    isPlaying.value = true;
    isPaused.value = false;
    isGameOver.value = false;

    // 生成初始方块
    activeBlock.value = generateRandomBlock();
    nextBlock.value = generateRandomBlock();

    // 启动游戏循环
    gameTimer.value = setInterval(moveBlockDown, gameSpeed.value);
  };

  // 暂停游戏
  const pauseGame = () => {
    if (!isPlaying.value || isPaused.value || isGameOver.value) return;

    isPaused.value = true;
    clearInterval(gameTimer.value);
  };

  // 继续游戏
  const resumeGame = () => {
    if (!isPlaying.value || !isPaused.value || isGameOver.value) return;

    isPaused.value = false;
    gameTimer.value = setInterval(moveBlockDown, gameSpeed.value);
  };

  // 重新开始游戏
  const restartGame = () => {
    clearInterval(gameTimer.value);
    startGame();
  };

  // -------------------------- 事件处理 --------------------------
  // 键盘事件处理
  const handleKeydown = (e) => {
    if (!isPlaying.value && !isGameOver.value) return;

    switch (e.key) {
      case 'ArrowLeft':
        moveBlock(-1, 0);
        break;
      case 'ArrowRight':
        moveBlock(1, 0);
        break;
      case 'ArrowDown':
        moveBlock(0, 1);
        break;
      case 'ArrowUp':
        rotateBlock();
        break;
      case ' ': // 空格键直接落地
        e.preventDefault(); // 防止页面滚动
        dropBlock();
        break;
      case 'p':
      case 'P': // P键暂停/继续
        isPaused.value ? resumeGame() : pauseGame();
        break;
    }
  };

  // 触摸开始事件
  const handleTouchStart = (e) => {
    touchStartX.value = e.touches[0].clientX;
    touchStartY.value = e.touches[0].clientY;
    touchStartTime.value = Date.now();
  };

  // 触摸结束事件
  const handleTouchEnd = (e) => {
    if (!isPlaying.value || isPaused.value || isGameOver.value) return;

    const touchEndX = e.changedTouches[0].clientX;
    const touchEndY = e.changedTouches[0].clientY;
    const diffX = touchEndX - touchStartX.value;
    const diffY = touchEndY - touchStartY.value;
    const touchDuration = Date.now() - touchStartTime.value;

    // 判断滑动方向和距离
    if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 20) {
      // 左右滑动 - 移动方块
      moveBlock(diffX > 0 ? 1 : -1, 0);
    } else if (Math.abs(diffY) > 20) {
      // 上下滑动
      if (diffY > 0) {
        // 向下滑动 - 加速下落
        moveBlock(0, 1);
      }
    } else if (touchDuration < 200) {
      // 短按 - 旋转方块
      rotateBlock();
    }
  };

  // 判断设备类型
  const checkDeviceType = () => {
    const userAgent = uni.getSystemInfoSync().userAgent;
    isMobile.value = /mobile|android|ios|iphone|ipad|ipod/i.test(userAgent);
  };

  // 生命周期钩子
  onMounted(() => {
    // 初始化游戏面板
    initBoard();

    // 检查设备类型
    checkDeviceType();

    // 添加事件监听
    document.addEventListener('keydown', handleKeydown);
    // 为游戏区域添加触摸事件
    const gameBoard = document.querySelector('.game-board');
    if (gameBoard) {
      gameBoard.addEventListener('touchstart', handleTouchStart);
      gameBoard.addEventListener('touchend', handleTouchEnd);
    }
  });

  onUnmounted(() => {
    // 清除定时器
    clearInterval(gameTimer.value);

    // 移除事件监听
    document.removeEventListener('keydown', handleKeydown);
    const gameBoard = document.querySelector('.game-board');
    if (gameBoard) {
      gameBoard.removeEventListener('touchstart', handleTouchStart);
      gameBoard.removeEventListener('touchend', handleTouchEnd);
    }
  });
</script>

<style scoped>
  .tetris-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20rpx;
    background-color: #f5f5f5;
    min-height: 100vh;
  }

  .game-header {
    text-align: center;
    margin-bottom: 30rpx;
    width: 100%;
    max-width: 600rpx;
  }

  .game-header h1 {
    color: #333;
    margin-bottom: 20rpx;
    font-size: 36rpx;
  }

  .game-stats {
    display: flex;
    justify-content: space-around;
    background-color: #fff;
    border-radius: 8rpx;
    padding: 15rpx;
    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  }

  .stat-item {
    text-align: center;
  }

  .stat-label {
    display: block;
    font-size: 24rpx;
    color: #666;
  }

  .stat-value {
    display: block;
    font-size: 30rpx;
    font-weight: bold;
    color: #333;
  }

  .game-main {
    display: flex;
    gap: 30rpx;
    align-items: flex-start;
    margin-bottom: 30rpx;
  }

  .game-board {
    position: relative;
    background-color: #fff;
    border: 2rpx solid #ccc;
    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
  }

  .board-row {
    display: flex;
  }

  .board-cell {
    box-sizing: border-box;
  }

  .active-block {
    position: absolute;
    box-sizing: border-box;
    transition: all 0.05s ease;
  }

  .next-block-preview {
    background-color: #fff;
    padding: 20rpx;
    border-radius: 8rpx;
    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
  }

  .next-block-preview h3 {
    margin: 0 0 15rpx 0;
    font-size: 28rpx;
    color: #333;
    text-align: center;
  }

  .preview-container {
    position: relative;
    background-color: #f0f0f0;
    border: 1rpx solid #e0e0e0;
  }

  .preview-block {
    position: absolute;
    box-sizing: border-box;
  }

  .game-controls {
    display: flex;
    gap: 15rpx;
    margin-bottom: 20rpx;
    flex-wrap: wrap;
    justify-content: center;
  }

  .game-controls button {
    padding: 12rpx 24rpx;
    background-color: #42b983;
    color: white;
    border: none;
    border-radius: 6rpx;
    font-size: 26rpx;
    cursor: pointer;
    transition: background-color 0.2s;
  }

  .game-controls button:hover {
    background-color: #359e75;
  }

  .mobile-controls {
    display: none;
    margin-top: 20rpx;
  }

  /* 移动端控制按钮仅在移动设备显示 */
  :is(.mobile-controls) {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 15rpx;
    width: 300rpx;
  }

  .control-row {
    display: flex;
    justify-content: center;
    gap: 15rpx;
  }

  .control-row:first-child {
    grid-column: 1 / 4;
    justify-content: center;
  }

  .control-row:last-child {
    grid-column: 1 / 4;
    justify-content: center;
  }

  .control-btn {
    width: 80rpx;
    height: 80rpx;
    border-radius: 8rpx;
    border: none;
    background-color: #42b983;
    color: white;
    font-size: 24rpx;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .control-btn.drop {
    width: 265rpx;
  }

  .game-over-modal {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
  }

  .modal-content {
    background-color: white;
    padding: 50rpx;
    border-radius: 10rpx;
    text-align: center;
    width: 80%;
    max-width: 400rpx;
  }

  .modal-content h2 {
    color: #e74c3c;
    margin-top: 0;
    margin-bottom: 30rpx;
  }

  .final-score,
  .final-lines {
    font-size: 28rpx;
    margin: 15rpx 0;
  }

  .modal-content button {
    margin-top: 20rpx;
    padding: 15rpx 30rpx;
    background-color: #42b983;
    color: white;
    border: none;
    border-radius: 6rpx;
    font-size: 26rpx;
    cursor: pointer;
  }

  .game-instructions {
    margin-top: 20rpx;
    font-size: 22rpx;
    color: #666;
    text-align: center;
    line-height: 1.5;
  }

  /* 响应式调整 */
  @media (max-width: 768px) {
    .game-main {
      flex-direction: column;
      align-items: center;
    }

    .next-block-preview {
      width: 100%;
      max-width: 300rpx;
    }
  }
</style>